<template>
    <div>
        <!-- 面包屑导航区域 -->
        <el-breadcrumb separator-class="el-icon-arrow-right">
            <el-breadcrumb-item>监控管理</el-breadcrumb-item>
            <el-breadcrumb-item :to="{ path: '/monitorDashboards' }">集群监控</el-breadcrumb-item>
            <el-breadcrumb-item>新增监控仪表盘</el-breadcrumb-item>
        </el-breadcrumb>

        <!-- 内容区 -->
        <div class="main-div" :style="innerStyle">

            <!-- 节点列表区 -->
            <el-card style="height: 100%; width: 300px;" :body-style="{ padding: '5px' }">
                <div slot="header" class="clearfix">
                    <span><i class="el-icon-share"></i> 列入监控的集群节点</span>
                </div>
                <el-table style="margin: 0;" :height="getInnerSize.height - 223" :data="clusterData.nodes">
                    <el-table-column prop="id" label="id" width="50"></el-table-column>
                    <el-table-column prop="ipaddr" label="地址" width="120"></el-table-column>
                    <el-table-column prop="name" label="名称"></el-table-column>
                </el-table>
            </el-card>

            <!-- 服务列表区 -->
            <el-card style="position: relative; height: 100%; margin-left: 5px; flex: 1;" :body-style="{ padding: '15px' }">
                <div slot="header" class="clearfix">
                    <span><i class="el-icon-edit-outline"></i> 数据与图形服务组合选择</span>
                </div>

                <el-form ref="monitorFormRef" :model="monitorForm" :rules="monitorFormRules" label-width="180px">
                    <el-row :gutter="20">
                        <el-col :span="16">
                            <el-form-item label="Grafana 图形服务" prop="grafanaId">
                                <el-select v-model="monitorForm.grafanaId" placeholder="请选择 Grafana 图形服务" style="width: 100%;" @change="selectedGrafanaChanged">
                                    <el-option v-for="item in grafanaData" :key="item.id" :label="item.ipaddr" :value="item.id">
                                        <span style="float: left">服务地址：{{ item.ipaddr }}</span>
                                        <span style="float: right; color: #8492a6; font-size: 12px">{{ item.home_path }}</span>
                                    </el-option>
                                </el-select>
                            </el-form-item>
                        </el-col>
                        <el-col :span="8">
                            <el-form-item label="Prometheus 数据源服务" prop="prometheusId">
                                <el-input v-model="monitorForm.prometheusId" placeholder="请选择 Prometheus 数据源服务" disabled></el-input>
                            </el-form-item>
                        </el-col>
                    </el-row>
                </el-form>

                <el-table :data="prometheusData" style="margin: 0; padding: 0;" :height="getInnerSize.height - 347" 
                    v-loading="loadingProcess" element-loading-text="正在加载数据源信息...">

                    <el-table-column prop="id" label="id" width="50"></el-table-column>
                    <el-table-column label="地址" width="150">
                        <template slot-scope="scope">
                            <el-radio v-model="monitorForm.prometheusId" :label="scope.row.id">{{scope.row.ipaddr}}</el-radio>
                        </template>
                    </el-table-column>
                    <el-table-column prop="user_normal" label="用户" width="100"></el-table-column>
                    <el-table-column prop="home_path" label="部署路径"></el-table-column>
                    <el-table-column label="" width="90">
                        <template slot-scope="scope">
                            <el-tag size="medium" type="success" v-if="scope.row.configured !== undefined">- 推荐 -</el-tag>
                            <el-tag size="medium" type="info" v-else>- 闲置 -</el-tag>
                        </template>
                    </el-table-column>
                </el-table>

                <div style="position: absolute; bottom: 10px; right: 25px;">
                    <el-button size="small" type="danger" icon="el-icon-back" @click="returnToPreviousPage">返 回</el-button>
                    <el-button size="small" type="primary" icon="el-icon-plus" @click="startDashboardAddition">创建仪表盘</el-button>
                </div>

            </el-card>
        </div>

        <!-- 添加监控仪表盘对话框 -->
        <el-dialog :title="`创建监控仪表盘`" 
            :visible.sync="addNewDashboardDialogVisible" 
            :before-close="handleDialogClose"
            :show-close="false"
            width="70%">
            
            <div class="installation-div">
                <el-card class="card-timeline">
                    <div slot="header">
                        <span>监控仪表盘创建流程</span>
                    </div>

                    <div style="height: 485px; overflow: auto;">
                        <el-timeline>
                            <el-timeline-item
                                v-for="(activity, index) in processInfo.activities"
                                :key="index"
                                :icon="activity.icon"
                                :type="activity.type"
                                :color="activity.color"
                                :size="activity.size"
                                :timestamp="activity.timestamp">
                                {{activity.content}}
                            </el-timeline-item>
                        </el-timeline>
                    </div>
                </el-card>

                <el-card class="card-timemessage">
                    <div slot="header">
                        <span>创建监控仪表盘流程日志</span>
                        <div :style="'float: right; color: ' + processInfo.titleColor + ';'">
                            <i :class="processInfo.titleIcon"></i>
                            {{processInfo.titleName}}
                            <el-button :style="processInfo.titleStyle" type="danger" icon="el-icon-more" size="mini" circle></el-button>
                        </div>
                    </div>
                    <div class="div-timemessage" :style="'height: 480px;'">
                        <textarea
                            v-model="processInfo.log" 
                            style="word-wrap:normal; outline: none; border: none; resize: none; width: 100%; height: 100%; font-size: 12px; font-family: 'Courier New', Courier, monospace;" 
                            readonly>
                        </textarea>
                    </div>
                </el-card>
            </div>

            <span slot="footer" class="dialog-footer">
                <el-button type="primary" @click="closeAddNewDashboardDialog" :disabled="(jobData.status === 0 || jobData.status === 1)">确 定</el-button>
                <!-- <el-button type="primary" @click="closeAddNewDashboardDialog">确 定</el-button> -->
            </span>
        </el-dialog>

    </div>
</template>

<script>
import { mapGetters } from 'vuex';
export default {
    data: function () {
        return {
            queryInfo: {
                query: '',
                pagenum: 1,
                pagesize: 9999
            },
            clusterData: {
                nodes: []
            },
            grafanaData: [],
            grafanaServiceCount: 0,
            prometheusData: [],
            prometheusServiceCount: 0,

            loadingProcess: false,
            monitorForm: {
                grafanaId: '',
                prometheusId: '',
                clusterId: ''
            },
            monitorFormRules: {
                grafanaId: [
                    { required: true, message: '请从下拉列表中选择一个图形服务作为监控可视化来源', trigger: 'blur' }
                ],
                prometheusId: [
                    { required: true, message: '请从表格中选择一项数据源服务', trigger: 'blur' }
                ]
            },
            addNewDashboardDialogVisible: false,
            jobData: {
                jobid: '0',
                status: 0,
                steps: [
                    {
                        name: '正在准备创建新的监控仪表盘...',
                        message: '即将开始创建新的监控仪表盘数据，请稍候...',
                        status: 0
                    }
                ]
            },
        }
    },
    computed: {
        ...mapGetters(['getInnerSize']),
        innerStyle: function () {
            return `height: ${this.getInnerSize.height - 160}px;`;
        },
        processInfo: function () {
            const activities = [];
            let logContent = '';
            let titleName = '即将开始创建监控仪表盘';
            const stepsCount = this.jobData.steps.length;
            for (let i = 0; i < stepsCount; i++) {
                const statusCode = this.jobData.steps[i].status;
                let iconName = '';
                let colorVal = '#E4E7ED';
                let timestamp= '';
                if (statusCode === -1) {
                    // 中断
                    iconName = 'el-icon-error';
                    colorVal = '#742A25';
                    timestamp = '执行错误';

                } else if (statusCode === 0) {
                    // 等待执行
                    iconName = 'el-icon-remove';
                    colorVal = '#E4E7ED';
                    timestamp = '等待执行';

                } else if (statusCode === 1) {
                    // 活动中
                    iconName = 'el-icon-loading';
                    colorVal = '#40AAFF';
                    timestamp = '正在执行';
                    titleName = this.jobData.steps[i].name;

                } else if (statusCode === 2) {
                    // 完成
                    iconName = 'el-icon-success';
                    colorVal = '#00FF00';
                    timestamp = '执行成功';
                }
                activities.push({
                    content: this.jobData.steps[i].name,
                    size: 'large',
                    icon: iconName,
                    color: colorVal,
                    timestamp: timestamp
                });

                if (statusCode !== 0) {
                    logContent += ` (${i + 1}/${stepsCount}) ${this.jobData.steps[i].name} \n`;
                    logContent += `${this.jobData.steps[i].message}\n\n`;
                    // logContent += `步骤状态：${this.jobData.steps[i].status}\n\n`;
                }
            }
            let titleIcon = 'el-icon-loading';
            let titleColor = '#E4E7ED';
            let titleStyle = 'display: none;';
            const statusCode = this.jobData.status;
            if (statusCode === -1) {
                titleIcon = "el-icon-close";
                titleColor = '#FF0000';
                titleName = '创建监控仪表盘失败';
                titleStyle = 'display: inline;';
            } else if (statusCode === 0) {
                titleIcon = "el-icon-warning-outline";
                titleColor = '#E4E7ED';
            } else if (statusCode === 1) {
                titleIcon = "el-icon-loading";
                titleColor = '#40AAFF';
            } else if (statusCode === 2) {
                titleIcon = "el-icon-check";
                titleName = '监控仪表盘创建完成';
                titleColor = '#67C23A';
            } else {
                titleIcon = "el-icon-minus";
            }
            return {
                activities: activities,
                log: logContent,
                titleIcon: titleIcon,
                titleName: titleName,
                titleColor: titleColor,
                titleStyle: titleStyle
            };
        }
    },
    mounted: function () {
        const cid = this.$route.query.cid;
        this.monitorForm.clusterId = cid;
        this.getClusterInfoById(cid);
        this.getGrafanaList();
        this.getPrometheusList();
    },
    methods: {
        getClusterInfoById: async function (cid) {
            const result = await this.$http.get(`clusters/${cid}`);
            const res = result.data;
            if (res.meta.status !== 201) return this.$message.error(`获取集群信息失败：${res.meta.msg}`);
            this.clusterData = res.data;
            // console.log("clusterData: ", this.clusterData);
        },
        getGrafanaList: async function () {
            const result = await this.$http.get('grafana', {
                params: this.queryInfo
            });
            const res = result.data;
            if (res.meta.status !== 200) return this.$message.error(`获取 Grafana 图形服务列表失败：${res.meta.msg}`);
            this.grafanaData = res.data.services;
            this.grafanaServiceCount = res.data.totalpage;
        },
        getPrometheusList: async function () {
            const result = await this.$http.get('prometheus', {
                params: this.queryInfo
            });
            const res = result.data;
            if (res.meta.status !== 200) return this.$message.error(`获取 Prometheus 数据源服务列表失败：${res.meta.msg}`);
            this.prometheusData = res.data.services;
            this.prometheusServiceCount = res.data.totalpage;
        },
        tableRowClassName: function ( { row, rowIndex } ) {
            if (rowIndex === 1) {
                return 'warning-row';
            } else if (rowIndex === 3) {
                return 'success-row';
            }
            return '';
        },
        selectedGrafanaChanged: function () {
            const grafana = this.grafanaData.find(grafana => grafana.id === this.monitorForm.grafanaId);
            this.prometheusData.forEach((prometheus, index) => {
                const included = grafana.datasources.some (ds => ds.id === prometheus.id);

                if (included) prometheus.configured = true;
                else prometheus.configured = undefined;

                this.$set(this.prometheusData, index, prometheus);
            });
        },
        handleDialogClose: function () {
        },
        returnToPreviousPage: function () {
            this.$router.go(-1);
        },
        startDashboardAddition: async function () {
            this.$refs.monitorFormRef.validate(async valid => {
                if (!valid) return this.$message.warning(`服务信息校验失败，请检查并选取需要配置的目标 Grafana 及 Prometheus 服务！`);
                
                const rm = await this.$confirm('信息校验成功，即将创建仪表盘及数据信息到监控服务中，是否继续?', '确认', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'question'
                }).catch(err => err);
                if (rm !== 'confirm') return this.$message.info('已取消添加仪表盘');

                this.addNewDashboardDialogVisible = true;
                console.log("monitorForm: ", this.monitorForm);

                // 1.0 发送任务处理流程委托
                const logMsg = await this.addDashboardAddition();
                if (logMsg) {
                    this.jobData.status = -1;
                    return this.$message.error(`创建监控仪表盘新增任务时发生错误: ${logMsg}`);
                }

                // 2.0 显示部署对话框，并添加后台任务轮询
                this.addNewDashboardDialogVisible = true;
                this.getProcessResult();
            })
        },
        // 发送任务处理流程委托
        addDashboardAddition: async function () {
            const result = await this.$http.put('grafana/dashboard/add', {
                id: this.monitorForm.grafanaId,
                pid: this.monitorForm.prometheusId,
                cid: this.monitorForm.clusterId
            });
            const res = result.data;
            if (res.meta.status !== 200) return res.meta.msg;
            this.jobData.jobid = res.data.job_id;
            console.log("新增监控仪表盘：", this.jobData.jobid);
        },
        getProcessResult: function () {
            setTimeout(async () => {
                // 4c1d4dd8-c593-4975-8f03-1fe9c27563c5
                const result = await this.$http.get(`process/${this.jobData.jobid}`);
                const res = result.data;
                if (res.meta.status !== 201) return this.$message.error(`获取任务处理信息失败：${res.meta.msg}`);
                this.jobData = res.data;

                console.log("this.jobData: ", this.jobData);

                // 任务如果非错误和完成状态，则循环监听任务回执消息
                const statusCode = res.data.status;
                if (statusCode !== -1 && statusCode !== 2) this.getProcessResult();
                else return '';
            }, 1000);
        },
        closeAddNewDashboardDialog: function () {
            this.addNewDashboardDialogVisible = false;
            if (this.jobData.status === 2) return this.$router.push('/monitorDashboards');
        }
    }
}
</script>

<style lang="less" scoped>
    .main-div {
        display: flex;
    }

    .nodes-div {
        flex: 200px;
    }

    .el-radio /deep/ .el-radio__label {
        font-size: 12px !important;
    }

    // 部署对话框
    .installation-div {
        display: flex;
        height: 590px;
    }

    .installation-div .card-timeline {
        width: 300px;
        margin: 10px;
    }

    .installation-div .card-timemessage {
        flex: 1;
        margin: 10px;
    }

    .div-submit {
        margin-top: 15px;
        display: flex;
        width: 100%;
        justify-content: center;
    }
</style>
